package com.h2cloud.JUCTest.patten;


import lombok.extern.slf4j.Slf4j;

import java.util.Arrays;
import java.util.List;

import static com.h2cloud.JUCTest.TimeUtil.Sleeper.sleep;

@Slf4j(topic = "c.TestGuardedObjectV2")
public class TestGuardedObjectV2 {
	public static void main(String[] args) {
		GuardedObjectV2 v2 = new GuardedObjectV2();
		new Thread(() -> {
			sleep(1);
			v2.complete(null);
			sleep(1);
			v2.complete(Arrays.asList("a", "b", "c"));
		}).start();

		Object response = v2.get(2500);
		if (response != null) {
			log.debug("get response: [{}] lines", ((List<String>) response).size());
		} else {
			log.debug("can't get response");
		}
	}
}


/**
 * 添加超时处理
 */
@Slf4j(topic = "c.GuardedObjectV2")
class GuardedObjectV2 {

	private Object response;
	private final Object lock = new Object();

	public Object get(long timeout) {
		synchronized (lock) {
			// 1) 记录最初时间
			long begin = System.currentTimeMillis();
			// 2) 已经经历的时间
			long passedTime = 0;
			while (response == null) {
				// 4) 假设 timeout 是 2500，结果在 1000 时唤醒了，且response == null。那么还有 1500 要等
				long waitTime = timeout - passedTime;
				log.debug("waitTime: {}", waitTime);
				if (waitTime <= 0) {
					log.debug("break...");
					break;
				}
				try {
					lock.wait(waitTime);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				// 3) 如果提前被唤醒，这时已经经历的时间假设为 1000
				passedTime = System.currentTimeMillis() - begin;
				log.debug("passedTime: {}, object is null {}", passedTime, response == null);
			}
			return response;
		}
	}

	public void complete(Object response) {
		synchronized (lock) {
			// 条件满足，通知等待线程
			this.response = response;
			log.debug("notify...");
			lock.notifyAll();
		}
	}
}
